package com.example.teaching_server.service;

import com.example.teaching_server.dto.GradeClassSimpleDTO;
import com.example.teaching_server.entity.ClassEntity;
import com.example.teaching_server.entity.Grade;
import com.example.teaching_server.entity.TeacherEntity;
import com.example.teaching_server.repository.ClassRepository;
import com.example.teaching_server.repository.GradeRepository;
import com.example.teaching_server.repository.TeacherRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 班级管理服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ClassService {

    private final ClassRepository classRepository;
    private final GradeRepository gradeRepository;
    private final TeacherRepository teacherRepository;

    /**
     * 获取所有班级
     */
    public List<ClassEntity> getAllClasses() {
        log.debug("查询所有班级");
        return classRepository.findAllByOrderByGradeGradeIdAscClassNameAsc();
    }

    /**
     * 根据年级名称获取班级
     */
    public List<ClassEntity> getClassesByGrade(String gradeLevel) {
        log.debug("根据年级名称查询班级: gradeLevel={}", gradeLevel);

        Grade grade = gradeRepository.findByGradeName(gradeLevel)
                .orElseThrow(() -> new RuntimeException("年级不存在: " + gradeLevel));

        return classRepository.findByGradeOrderByClassNameAsc(grade);
    }

    /**
     * 获取所有年级列表
     */
    public List<String> getAllGradeLevels() {
        log.debug("查询所有年级名称");
        return gradeRepository.findAllGradeNames();
    }

    /**
     * 获取老师所教的所有班级
     */
    public List<GradeClassSimpleDTO> getTeacherClassList(Long teacherId) {
        log.debug("查询教师所教班级列表: teacherId={}", teacherId);

        validateTeacherExists(teacherId);

        List<ClassEntity> classes = classRepository.findByTeachersTeacherIdOrderByGradeGradeNameAscClassNameAsc(teacherId);

        return classes.stream()
                .map(this::convertToGradeClassSimpleDTO)
                .collect(Collectors.toList());
    }

    /**
     * 获取老师所教的所有班级名称
     */
    public List<String> getTeacherClassNames(Long teacherId) {
        log.debug("查询教师所教班级名称: teacherId={}", teacherId);

        List<ClassEntity> classes = classRepository.findByTeachersTeacherIdOrderByGradeGradeNameAscClassNameAsc(teacherId);

        return classes.stream()
                .map(this::generateDisplayName)
                .collect(Collectors.toList());
    }

    /**
     * 根据年级ID获取班级
     */
    public List<ClassEntity> getClassesByGradeId(Long gradeId) {
        log.debug("根据年级ID查询班级: gradeId={}", gradeId);

        Grade grade = gradeRepository.findById(gradeId)
                .orElseThrow(() -> new RuntimeException("年级不存在: " + gradeId));

        return classRepository.findByGradeOrderByClassNameAsc(grade);
    }

    /**
     * 根据关键字搜索班级
     */
    public List<ClassEntity> searchClasses(String keyword) {
        log.debug("搜索班级: keyword={}", keyword);

        if (keyword == null || keyword.trim().isEmpty()) {
            return getAllClasses();
        }

        return classRepository.findByClassNameContainingIgnoreCaseOrderByGradeGradeNameAscClassNameAsc(keyword);
    }

    /**
     * 根据年级和关键字搜索班级
     */
    public List<ClassEntity> searchClassesByGradeAndKeyword(String gradeLevel, String keyword) {
        log.debug("根据年级和关键字搜索班级: gradeLevel={}, keyword={}", gradeLevel, keyword);

        List<ClassEntity> classes;

        if (gradeLevel != null && !gradeLevel.trim().isEmpty()) {
            Grade grade = gradeRepository.findByGradeName(gradeLevel)
                    .orElseThrow(() -> new RuntimeException("年级不存在: " + gradeLevel));
            classes = classRepository.findByGradeOrderByClassNameAsc(grade);
        } else {
            classes = getAllClasses();
        }

        if (keyword != null && !keyword.trim().isEmpty()) {
            classes = classes.stream()
                    .filter(classEntity -> classEntity.getClassName().toLowerCase().contains(keyword.toLowerCase()))
                    .collect(Collectors.toList());
        }

        return classes;
    }

    /**
     * 获取班级详情
     */
    public ClassEntity getClassDetail(Long classId) {
        log.debug("查询班级详情: classId={}", classId);
        return classRepository.findById(classId)
                .orElseThrow(() -> new RuntimeException("班级不存在: " + classId));
    }

    /**
     * 获取班级数量统计
     */
    public long getClassCount() {
        log.debug("查询班级总数");
        return classRepository.count();
    }

    /**
     * 按年级统计班级数量
     */
    public List<Object[]> getClassCountByGrade() {
        log.debug("按年级统计班级数量");
        return classRepository.countClassesByGrade();
    }

    /**
     * 检查班级名称是否已存在
     */
    public boolean isClassNameExists(String className) {
        log.debug("检查班级名称是否存在: className={}", className);
        return classRepository.findByClassName(className).isPresent();
    }

    /**
     * 检查班级名称是否已存在（排除指定班级ID）
     */
    public boolean isClassNameExistsExcept(String className, Long excludeClassId) {
        log.debug("检查班级名称是否存在（排除指定ID）: className={}, excludeClassId={}", className, excludeClassId);
        return classRepository.findByClassNameAndIdNot(className, excludeClassId).isPresent();
    }

    /**
     * 生成显示名称
     */
    private String generateDisplayName(ClassEntity classEntity) {
        StringBuilder displayName = new StringBuilder();

        if (classEntity.getGrade() != null && classEntity.getGrade().getGradeName() != null) {
            displayName.append(classEntity.getGrade().getGradeName());
        }

        if (classEntity.getClassName() != null) {
            displayName.append(classEntity.getClassName());
        }

        if (displayName.isEmpty()) {
            displayName.append("未知班级");
        }

        return displayName.toString();
    }

    /**
     * 转换为GradeClassSimpleDTO
     */
    private GradeClassSimpleDTO convertToGradeClassSimpleDTO(ClassEntity classEntity) {
        GradeClassSimpleDTO dto = new GradeClassSimpleDTO();
        dto.setClassId(classEntity.getClassId());
        dto.setGradeId(classEntity.getGrade().getGradeId());
        dto.setDisplayName(generateDisplayName(classEntity));
        return dto;
    }

    /**
     * 验证教师是否存在
     */
    private void validateTeacherExists(Long teacherId) {
        if (!teacherRepository.existsById(teacherId)) {
            throw new RuntimeException("教师不存在: " + teacherId);
        }
    }
}
